#ifndef FLOW_CHART_H
#define FLOW_CHART_H

#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>
#include <string>
#include <time.h>
#include "typedef.h"
#include "MinuteTimer.h"

using namespace boost::statechart;

struct CWaitLoginState;
struct CWaitValidationState;
struct CEvValidateBegin : event<CEvValidateBegin> {};
class CSession;

class IEvents
{
public:
    ~IEvents() {}

    virtual void OnLoginReq(std::string strUserName, std::string strPwd) const = 0;

    virtual void OnRcvValidationResult(std::string strUser, bool bResult, uint32 nUserID) const = 0;
};

struct CFSM : state_machine<CFSM, CWaitLoginState>
{
    CFSM(CSession * );

    void OnLoginReq(std::string strUserName, std::string strPwd);

    void OnRcvValidationResult(std::string strUser, bool bResult, uint32 nUserID);

    void ValidateUserInfo(std::string strUserName, std::string strPwd) const;

    CSession * GetSession() const;
protected:
    CSession * m_pSession;
};

struct CWaitLoginState : simple_state<CWaitLoginState, CFSM>, public IEvents, public CMinuteTimerSubscriber
{
    typedef transition<CEvValidateBegin, CWaitValidationState> reactions;

    CWaitLoginState();

    ~CWaitLoginState();

    virtual void OnLoginReq(std::string strUserName, std::string strPwd) const;

    virtual void OnRcvValidationResult(std::string strUser, bool bResult, uint32 nUserID) const {}

    virtual void OnTrigger(time_t);
private:
    time_t m_tStartTime;
};

struct CWaitValidationState : simple_state<CWaitValidationState, CFSM>, public IEvents, public CMinuteTimerSubscriber
{
    CWaitValidationState();

    ~CWaitValidationState();

    virtual void OnLoginReq(std::string strUserName, std::string strPwd) const {}

    virtual void OnRcvValidationResult(std::string strUser, bool bResult, uint32 nUserID) const;

    virtual void OnTrigger(time_t);
private:
    time_t m_tStartTime;
    static uint32 nToken;
};

#endif  // endif of FLOW_CHART_H

